package com.guptarulie.jmeter.protocol.mm7.submitvasmm;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Date;


import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testbeans.TestBean;

/**
 *User: Mat Rule
 *User: Gaurav Gupta
 *Date: Jan 2009
 */

public class MM7VasMMSubmitSampler extends AbstractSampler implements TestBean {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4459287513364056191L;
	private static final String mm7ServerName = "MM7VasMMSubmitSampler.mm7ServerName"; //$NON-NLS-1$    
	private static final String mm7User = "MM7VasMMSubmitSampler.mm7User"; //$NON-NLS-1$
	private static final String mm7Pass = "MM7VasMMSubmitSampler.mm7Pass"; //$NON-NLS-1$
	private static final String mm7ToNumber = "MM7VasMMSubmitSampler.mm7ToNumber"; //$NON-NLS-1$
	private static final String mm7VaspId = "MM7VasMMSubmitSampler.mm7VaspId"; //$NON-NLS-1$
	private static final String mm7PortNumber = "MM7VasMMSubmitSampler.mm7PortNumber"; //$NON-NLS-1$
	private static final String mm7DeliveryOn = "MM7VasMMSubmitSampler.mm7DeliveryOn"; //$NON-NLS-1$
	private static final String mm7TimeOut = "MM7VasMMSubmitSampler.mm7TimeOut"; //$NON-NLS-1$
	private static final String mm7MsgContent = "MM7VasMMSubmitSampler.mm7MsgContent"; //$NON-NLS-1$
	private static final String mm7MsgContentCust = "MM7VasMMSubmitSampler.mm7MsgContentCust"; //$NON-NLS-1$
	private static long increment;
	private boolean didTimeOut = false;
	
	public String getmm7ServerName() {
        return getPropertyAsString(mm7ServerName);
    }

    public void setmm7ServerName(String newmm7ServerName) {
        this.setProperty(mm7ServerName, newmm7ServerName);
    }
    
	public String getmm7PortNumber() {
        return getPropertyAsString(mm7PortNumber);
    }

    public void setmm7PortNumber(String newmm7PortNumber) {
        this.setProperty(mm7PortNumber, newmm7PortNumber);
    }

    public String getmm7User() {
        return getPropertyAsString(mm7User);
    }

    public void setmm7User(String newmm7User) {
        this.setProperty(mm7User, newmm7User);
    }
    
    public String getmm7Pass() {
        return getPropertyAsString(mm7Pass);
    }

    public void setmm7Pass(String newmm7Pass) {
        this.setProperty(mm7Pass, newmm7Pass);
    }

	public String getmm7ToNumber() {
        return getPropertyAsString(mm7ToNumber);
    }

    public void setmm7ToNumber(String newmm7ToNumber) {
        this.setProperty(mm7ToNumber, newmm7ToNumber);
    }
    
	public String getmm7MsgContent() {
        return getPropertyAsString(mm7MsgContent);
    }

    public void setmm7MsgContent(String newmm7MsgContent) {
        this.setProperty(mm7MsgContent, newmm7MsgContent);
    }
    
	public String getmm7MsgContentCust() {
        return getPropertyAsString(mm7MsgContentCust);
    }

    public void setmm7MsgContentCust(String newmm7MsgContentCust) {
        this.setProperty(mm7MsgContentCust, newmm7MsgContentCust);
    }
    
	public String getmm7VaspId() {
        return getPropertyAsString(mm7VaspId);
    }

    public void setmm7VaspId(String newmm7VaspId) {
        this.setProperty(mm7VaspId, newmm7VaspId);
    }
    
	public String getmm7TimeOut() {
        return getPropertyAsString(mm7TimeOut);
    }

    public void setmm7TimeOut(String newmm7TimeOut) {
        this.setProperty(mm7TimeOut, newmm7TimeOut);
    }
    
	public String getmm7DeliveryOn() {
        return getPropertyAsString(mm7DeliveryOn);
    }

    public void setmm7DeliveryOn(String newmm7DeliveryOn) {
        this.setProperty(mm7DeliveryOn, newmm7DeliveryOn);
    }
    
    private StringBuffer SendMM7Submit(SampleResult result) {
        StringBuffer responseData = new StringBuffer();
        try {
    	
            String hostname = getmm7ServerName();
            int port = new Integer(getmm7PortNumber());
            InetAddress  addr = InetAddress.getByName(hostname);
            Socket sock = new Socket(addr, port);
            sock.setSoTimeout( new Integer(getmm7TimeOut()) );
            
            BufferedWriter  wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),"UTF-8"));
            StringBuffer xmlContents = new StringBuffer();
            StringBuffer httpContents = new StringBuffer();

            String utf8UserPass = getmm7User()+":"+getmm7Pass();
            String authHeaderValue = new sun.misc.BASE64Encoder().encode(utf8UserPass.getBytes());

            // delivery report off by default
            String deliveryReport = "False";
            
            if (getmm7DeliveryOn().indexOf("On") != -1 ) {
            	deliveryReport = "True";
            } else if(getmm7DeliveryOn().indexOf("Off") != -1 ) {
            	deliveryReport = "False";
            } else {
            	deliveryReport = "False";
            	System.err.println("Delivery report value not valid. Defaulting to False");
            	System.err.println(getmm7DeliveryOn());
            }
            
            //create a new individual transaction id. use millisecond time+a static increment+threadname
            long epochTime = new Date().getTime();
            increment++;
            String transId = epochTime + "-" + increment + "-" + getThreadName().toString();
            	
            //keep seperate so we can quickly calculate content length
			xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C---\r\n");
			xmlContents.append("Content-Type: text/xml; charset=utf-8\r\n");
			xmlContents.append("Content-ID: <mm7_msg>\r\n");
			xmlContents.append("\r\n");
			xmlContents.append("<?xml version='1.0' ?>\r\n");
			xmlContents.append("<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n");
			xmlContents.append("<env:Header>\r\n");
			xmlContents.append("<mm7:TransactionID xmlns:mm7=\"http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2\" env:mustUnderstand=\"1\">\r\n");
			xmlContents.append(transId+"\r\n");
			xmlContents.append("</mm7:TransactionID>\r\n");
			xmlContents.append("</env:Header>\r\n");
			xmlContents.append("<env:Body>\r\n");
			xmlContents.append("<SubmitReq xmlns=\"http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2\">\r\n");
			xmlContents.append("<MM7Version>5.3.0</MM7Version>\r\n");
			xmlContents.append("<SenderIdentification>\r\n");
			xmlContents.append("<VASPID>"+getmm7VaspId()+"</VASPID>\r\n");
			xmlContents.append("<VASID>my id</VASID>\r\n");
			xmlContents.append("</SenderIdentification>\r\n");
			xmlContents.append("<Recipients>\r\n");
			xmlContents.append("<To>\r\n");
			xmlContents.append("<Number>46701111111</Number>\r\n");
			xmlContents.append("</To>\r\n");
			xmlContents.append("</Recipients>\r\n");
			xmlContents.append("<DeliveryReport>"+deliveryReport+"</DeliveryReport>\r\n");
			xmlContents.append("<Subject>JMeter Test #"+transId+"</Subject>\r\n");
			xmlContents.append("<Content href=\"cid:mms_cid\" />\r\n");
			xmlContents.append("</SubmitReq>\r\n");
			xmlContents.append("</env:Body>\r\n");
			xmlContents.append("</env:Envelope>\r\n");
			xmlContents.append("\r\n");
			
			if (getmm7MsgContent().indexOf("Text") != -1 ) {
				// Text message contents
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C---\r\n");
				xmlContents.append("Content-Type: multipart/mixed; boundary=\"---mime-boundary-C97CAD9D.029FABDE---\"\r\n");
				xmlContents.append("Content-ID: <mms_cid>\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE---\r\n");
				xmlContents.append("Content-Type: text/plain\r\n");
				xmlContents.append("Content-ID: <40F64F99.txt>\r\n");
				xmlContents.append("Content-location: 40F64F99.txt\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("test from jmeter, hello world!\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE-----\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C----- ");
				xmlContents.append("\r\n");
			} else if (getmm7MsgContent().indexOf("Image") != -1 ) {
				// TODO change contents to image file
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C---\r\n");
				xmlContents.append("Content-Type: multipart/mixed; boundary=\"---mime-boundary-C97CAD9D.029FABDE---\"\r\n");
				xmlContents.append("Content-ID: <mms_cid>\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE---\r\n");
				xmlContents.append("Content-Type: text/plain\r\n");
				xmlContents.append("Content-ID: <40F64F99.txt>\r\n");
				xmlContents.append("Content-location: 40F64F99.txt\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("test from jmeter, hello world!\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE-----\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C----- ");
				xmlContents.append("\r\n");
			} else if (getmm7MsgContent().indexOf("Audio") != -1 ) {
				// TODO change contents to audio file
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C---\r\n");
				xmlContents.append("Content-Type: multipart/mixed; boundary=\"---mime-boundary-C97CAD9D.029FABDE---\"\r\n");
				xmlContents.append("Content-ID: <mms_cid>\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE---\r\n");
				xmlContents.append("Content-Type: text/plain\r\n");
				xmlContents.append("Content-ID: <40F64F99.txt>\r\n");
				xmlContents.append("Content-location: 40F64F99.txt\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("test from jmeter, hello world!\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE-----\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C----- ");
				xmlContents.append("\r\n");
			} else {
				//default to text if unknown
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C---\r\n");
				xmlContents.append("Content-Type: multipart/mixed; boundary=\"---mime-boundary-C97CAD9D.029FABDE---\"\r\n");
				xmlContents.append("Content-ID: <mms_cid>\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE---\r\n");
				xmlContents.append("Content-Type: text/plain\r\n");
				xmlContents.append("Content-ID: <40F64F99.txt>\r\n");
				xmlContents.append("Content-location: 40F64F99.txt\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("test from jmeter, hello world!\r\n");
				xmlContents.append("-----mime-boundary-C97CAD9D.029FABDE-----\r\n");
				xmlContents.append("\r\n");
				xmlContents.append("-----mime-boundary-F032A15B.98A2DA1C----- ");
				xmlContents.append("\r\n");
			} // TODO need to add code if its a custom file!
			
            //http header stuff, in wrong order, but so we can calculate the content length
			httpContents.append("POST /mm7 HTTP/1.0\r\n");
			httpContents.append( ("Authorization: Basic " + authHeaderValue + "\r\n" ) );
			httpContents.append("Host: "+getmm7ServerName()+"\r\n");
			httpContents.append("Content-Length: " + xmlContents.length() + "\r\n");
			httpContents.append("Content-Type: multipart/related; boundary=\"---mime-boundary-F032A15B.98A2DA1C---\"; type=\"text/xml\"; start=\"<mm7_msg>\""+"\r\n");
			httpContents.append("SOAPAction: \"\"\r\n");
			httpContents.append("\r\n");
			
            // add the http and xml contents buffers to the mix
			wr.write(httpContents.toString());
            wr.write(xmlContents.toString());
            wr.write(xmlContents.toString());
            
			//Send data
            wr.flush();
            
            //write the request data
            result.setRequestHeaders(httpContents.toString()+"\n\r"+xmlContents.toString());
            result.setSamplerData("");
            
            // Response
            BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            String inStream;
            
            while((inStream = rd.readLine()) != null)
            	responseData.append(inStream+"\r\n");
            } 
        catch (SocketTimeoutException se) {
        	didTimeOut = true;
        }
        catch (Exception e) {
                e.printStackTrace();
        }
		return responseData;
    }
    
	@Override
	public SampleResult sample(Entry e) {
		// TODO Auto-generated method stub
        
        SampleResult result = new SampleResult();
        
        result.setDataEncoding(SampleResult.DEFAULT_HTTP_ENCODING);
        result.setDataType(SampleResult.TEXT);
        result.setSampleLabel(getName());

        //set the start
        result.sampleStart();
        //SendMM7Submit Message and return the response data
        StringBuffer responseData = SendMM7Submit(result);
        // end sample
        result.sampleEnd();
        if ( didTimeOut != true ) {
	        //quick way of pulling out the result
	        int resDatLoc = responseData.indexOf("StatusCode>");
	        String responseCode = responseData.substring(resDatLoc+11, resDatLoc+15);
	        result.setResponseCode(responseCode);
	        result.setResponseData(responseData.toString().getBytes());
	        //1000 is successful. Anything else indicates a problem, user looks in response data
	        if ( responseCode.indexOf("1000") != -1 ) {
	        	result.setSuccessful(true);	
	        } else {
	        	result.setSuccessful(false);
	        }
        } else {
        	result.setResponseCode("TIMEOUT");
        	result.setResponseMessage("TIMEOUT");
        	result.setSuccessful(false);
        }
		return result;
	}
}
